package util;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;

import javax.swing.WindowConstants;
import javax.swing.SwingUtilities;


public class ClientDummie extends javax.swing.JFrame {

	private static final long serialVersionUID = -7550265558451645112L;
	
	private JScrollPane jScrollPaneMessages;
	private JButton jSendButton;
	private JTextField jSendText;
	private JTextArea jTxtMessages;
	
	private int port;
	private String remoteHost;
	private Socket mySocket;
	private BufferedReader input;
	private PrintStream output;
	private JTextField jPortText;
	private JTextField jHostText;
	private JButton jConnectButton;
	
	private boolean connected=false;

	// MAIN
	/**
	* Main Executable class.
	*/
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				ClientDummie inst = new ClientDummie(0,null);
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
			}
		});
	}
	
	// CONSTRUCTOR
	/**
	 * Creates a new ClientDummie object.
	 */
	public ClientDummie(int port, String remotehost) {
		super();
		this.port = port;
		this.remoteHost = remotehost;
		this.initGUI();
		inputListener.start();
	}
	
	// PRIVATE METHODS
	/**
	 * Initialize the user interface.
	 */
	private void initGUI() {
		try {
			
			// Define General Behavior 
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			addWindowListener(closingWindow);
			getContentPane().setLayout(null);
			this.setResizable(false);
			this.setTitle("DummieClient");

			// Change Look And Feel
		    try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } 
		    	catch(Exception e) { System.out.println("Error setting native LAF: " + e);  }

		    // Declare Components
			jScrollPaneMessages = new JScrollPane();
			jSendButton = new JButton();
			jSendText = new JTextField();
			jTxtMessages = new JTextArea();
			jPortText = new JTextField();
			jHostText = new JTextField();
			jConnectButton = new JButton();
			
			// Text box where the host address must be written
			jHostText.setBounds(0,0,150,20);
			jHostText.setText("localhost");
			
			// Text box where the host port must be written
			jPortText.setBounds(150, 0, 50, 20);
			jPortText.setText("2501");
			
			// Button to start or end a connection with the server
			jConnectButton.setBounds(200, 0, 100, 20);
			jConnectButton.setText("Connect");
			jConnectButton.addActionListener(pressConnectButton);

			// Scroll pane that contains jTxtMessages
			jScrollPaneMessages.setBounds(0, 25, 320, 150);
			jScrollPaneMessages.setViewportView(jTxtMessages);
			
			// TextAres where messages received are written 
			jTxtMessages.setEditable(false);

			// Button to send a message
			jSendButton.setText("Send");
			jSendButton.setBounds(200,180, 100, 20);
			jSendButton.addActionListener(pressSendButton);
			jSendButton.setEnabled(false);
			
			// TextBox where the message to the server must be written
			jSendText.setBounds(0, 180, 200, 20);
			jSendText.addActionListener(pressSendButton);
			jSendText.setEnabled(false);

			// Adding Components 
			getContentPane().add(jScrollPaneMessages);
			getContentPane().add(jSendButton);			
			getContentPane().add(jSendText);
			getContentPane().add(jConnectButton);
			getContentPane().add(jHostText);
			getContentPane().add(jPortText);

			// Pack !!
			pack();
			
			// Set Size!
			this.setSize(310, 230);
			
		} catch (Exception e) { e.printStackTrace(); }
		
		
	}

	/**
	 * Set up the connection with the server.
	 */
	private void connect() {
		try {
			remoteHost = jHostText.getText();
			port = Integer.parseInt(jPortText.getText());
			
			mySocket = new Socket(remoteHost,port);
			input = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
			output = new PrintStream(mySocket.getOutputStream());
			connected = true;
			jSendButton.setEnabled(true);
			jSendText.setEnabled(true);
			jConnectButton.setText("Disconnect");
		} catch (ConnectException e) { jTxtMessages.setText(jTxtMessages.getText()+"No se puede conectar al server\r\n");}
		  catch (UnknownHostException e) { e.printStackTrace(); } 
		  catch (IOException e) { e.printStackTrace(); }
	}

	/**
	 * Close the connection with the server.
	 */
	private void disconnect() {
		try {
			
			connected = false;
			
			if (mySocket!=null) mySocket.close();
			if (mySocket!=null) input.close();
			if (mySocket!=null) output.close();
			
			
			
			jSendButton.setEnabled(false);
			jSendText.setEnabled(false);
			jConnectButton.setText("Connect");

		} catch (IOException e) {e.printStackTrace(); }
	}

	// INNER CLASSES & LISTENERS
	/**
	 * Inner class that listens the input buffer and shows its content to a TextArea object
	 */
	private class InputListener extends Thread {
		private boolean end=false;
		public void end() {this.end = true;}
		public void run() {
			do {
				
				try { Thread.sleep(500); } catch (InterruptedException e2) { e2.printStackTrace();}
				
				if (connected && input!=null) {
					try {
						String readLine = input.readLine();
						jTxtMessages.setText(jTxtMessages.getText()+readLine+"\r\n");
					} catch (SocketException e) { jTxtMessages.setText(jTxtMessages.getText()+"Connection Closed\r\n"); }
					catch (IOException e1) { e1.printStackTrace(); }
				}
			System.out.println("Listener Loop");
			}while(!end );
		}
	}
	InputListener inputListener = new InputListener();
	
	/**
	 * ActionListener fired when the connection button is pressed. 
	 */
	ActionListener pressConnectButton = new ActionListener() {
		@Override public void actionPerformed(ActionEvent a) {
			if (!connected) {
				connect();
				  
			} else {
				
				disconnect();
	
			}
		}
	};
	
	/**
	 * ActionListener fired when the send button is pressed or ENTER key is pressing while writing on the send text field..
	 */
	ActionListener pressSendButton = new ActionListener() {
		@Override public void actionPerformed(ActionEvent e) {
			output.println(jSendText.getText());
			jSendText.setText("");
		}
	};
	
	
	/**
	 * ActionListener fired when the client dummie windows performs an event.
	 */
	WindowListener closingWindow = new WindowListener() {

		@Override public void windowClosing(WindowEvent e) { 
			if(connected) disconnect();
			inputListener.end();
			System.out.println("Closing");
		}
		
		@Override public void windowOpened(WindowEvent e) {}
		@Override public void windowIconified(WindowEvent e) {}
		@Override public void windowDeiconified(WindowEvent e) { }
		@Override public void windowDeactivated(WindowEvent e) { }
		@Override public void windowClosed(WindowEvent e) { }
		@Override public void windowActivated(WindowEvent e) { }
	};

}
